import { jsonParse } from '@/utils';
import * as fs from './fs-helpers';
import { getHandles } from './utils';

export type IDBFindAttachmentParams = {
  ids: string[];
};

export type IDBAddAttachmentParams = {
  id: string;
  file: File;
};

export type IDBAttachmentManifestRecord = {
  /** 附件id */
  id: string;
  /** 附件文件名 */
  fileName: string;
};

const controller = () => {
  const _getHandles = async () => getHandles('attachments');

  const getMainfestJson = async () => {
    const handles = await _getHandles();
    return jsonParse<IDBAttachmentManifestRecord[]>(await fs.readFile(await handles.manifest.getFile())) ?? [];
  };

  const getAttachmentName = (id: string, name: string) => `{${id}}${name}`;

  const find = async ({ ids }: IDBFindAttachmentParams) => {
    try {
      const handles = await _getHandles();
      const manifest = await getMainfestJson();
      if (!manifest) return { success: true };
      const records = manifest.filter((v) => ids.includes(v.id));
      if (!records.length) return { success: true, data: [] };
      const data = await Promise.all(
        records.map(async (v) => {
          const file = await (await handles.data.getFileHandle(getAttachmentName(v.id, v.fileName))).getFile();
          return { id: v.id, file: new File([file], v.fileName, { type: file.type }) };
        }),
      );
      return { success: true, data };
    } catch (e) {
      console.error(e);
      return { success: false, message: '查找失败' };
    }
  };

  const add = async (data: IDBAddAttachmentParams[]) => {
    try {
      if (!data.length) return;
      const handles = await _getHandles();
      const mainfestJson = await getMainfestJson();
      await Promise.all(
        data.map(async (v) => {
          fs.writeFile(await handles.data.getFileHandle(getAttachmentName(v.id, v.file.name), { create: true }), v.file);
          mainfestJson.push({ id: v.id, fileName: v.file.name });
        }),
      );
      await fs.writeFile(handles.manifest, JSON.stringify(mainfestJson));
      return { success: true };
    } catch (e) {
      console.error(e);
      return { success: false, message: '添加失败' };
    }
  };

  const del = async (ids: string[]) => {
    try {
      const handles = await _getHandles();
      const mainfestJson = await getMainfestJson();
      const deleted = mainfestJson.filter((v) => ids.includes(v.id));
      if (!deleted.length) return { success: true };
      await Promise.all(
        deleted.map(async ({ id, fileName }) => {
          await handles.data.removeEntry(getAttachmentName(id, fileName), { recursive: true });
        }),
      );
      await fs.writeFile(handles.manifest, JSON.stringify(mainfestJson.filter((v) => !ids.includes(v.id))));
      return { success: true };
    } catch (e) {
      console.error(e);
      return { success: false, message: '删除失败' };
    }
  };

  return {
    add,
    find,
    delete: del,
    getHandles: _getHandles,
  };
};

export const attachment = controller();
